package cn.kow.kmall.controller;

import cn.kow.kmall.common.enums.KmallResultEnum;
import cn.kow.kmall.common.wechat.WeChatApi;
import cn.kow.kmall.common.wechat.WeChatUtils;
import cn.kow.kmall.common.wechat.request.Code2SessionRequest;
import cn.kow.kmall.common.wechat.response.Code2SessionResponse;
import cn.kow.kmall.common.wechat.response.PhoneNumberResponse;
import cn.kow.kmall.config.WXAccountConfig;
import cn.kow.kmall.core.exception.ServiceException;
import cn.kow.kmall.core.response.KmallResult;
import cn.kow.kmall.core.util.JwtTokenUtils;
import cn.kow.kmall.pojo.dto.UserDTO;
import cn.kow.kmall.pojo.dto.WechatPhoneLoginDTO;
import cn.kow.kmall.pojo.entity.User;
import cn.kow.kmall.pojo.vo.UserInfoVO;
import cn.kow.kmall.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: lijun
 * @Description: 登录
 * @Date: Created in 2019-05-13 15:27
 * @Modified By:
 */
@Slf4j
@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    private WXAccountConfig wxAccountConfig;

    @Autowired
    private UserService userService;

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expire}")
    private Long expire;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 微信小程序登录
     *
     * @param loginDTO
     * @return
     */
    @PostMapping("/weapp/phone")
    public Object wxLogin(@RequestBody WechatPhoneLoginDTO loginDTO) {
        String code = loginDTO.getCode();
        String key = "wx:login:code:" + code;
        // 从缓存中获取
        Code2SessionResponse response;
        if (redisTemplate.hasKey(key)) {
            response = (Code2SessionResponse) redisTemplate.opsForValue().get(key);
        } else {
            // 获取小程序 openId， sessionKey
            Code2SessionRequest request = new Code2SessionRequest();
            request.setCode(code);
            request.setAppId(wxAccountConfig.getAppId());
            request.setSecret(wxAccountConfig.getAppSecret());
            response = WeChatApi.code2Session(request);
            if (0 != response.getErrCode()) {
                return KmallResult.build(KmallResultEnum.LOGIN_FAIL);
            }
            // 缓存Code2SessionResponse
            redisTemplate.opsForValue().set(key, response, 30, TimeUnit.MINUTES);
        }

        // 号码解密
        String openid = response.getOpenid();
        String unionid = response.getUnionid();
        String sessionKey = response.getSessionKey();
        String iv = loginDTO.getIv();
        String encryptedData = loginDTO.getEncryptedData();
        PhoneNumberResponse phoneNumberResponse = WeChatUtils.getPhoneNumber(encryptedData, sessionKey, iv);
        if (null == phoneNumberResponse) {
            throw new ServiceException(KmallResultEnum.WXC_DECRYPT_FAIL);
        }
        String phone = phoneNumberResponse.getPhoneNumber();

        User user = userService.getUserByOpenid(openid);
        if (user == null) {
            UserDTO userDTO = new UserDTO();
            userDTO.setOpenid(openid);
            userDTO.setUnionid(unionid);
            userDTO.setPhone(phone);
            user = userService.saveUser(userDTO);
        } else {
            if (user.getStatus() != 1) {
                throw new ServiceException(KmallResultEnum.USER_NOT_FIND);
            }
        }

        Map<String, Object> claims = new HashMap<>();
        claims.put("uid", user.getUid());
        claims.put("openid", openid);
        String token = JwtTokenUtils.generateToken(user.getName(), claims, secret, expire);
        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfoVO);
        return KmallResult.success().put("token", token).put("userInfo", userInfoVO);
    }

    /**
     * 手机号登录
     * @param phone
     * @param code
     * @return
     */
    @PostMapping(value = "/phone")
    public Object getUserInfo(
            @NotEmpty(message = "手机号不能为空")
            @Pattern(regexp = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$", message = "手机号错误")
            @RequestParam String phone,
            @NotEmpty(message = "验证码不能为空")
            @RequestParam String code) {
        // 验证码校验
        // 发放token
        return KmallResult.success();
    }

}
